package com.foruo.code.service;

import com.foruo.code.config.Config;
import com.foruo.code.entity.ColumnModel;
import com.foruo.code.entity.DataBaseModel;
import com.foruo.code.entity.TableModel;
import com.foruo.code.utils.ConfigurationHelper;
import com.foruo.code.utils.StringUtils;
import com.foruo.code.utils.db.DBMangerPool;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import javax.swing.tree.TreePath;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 代码生成服务
 * @author gaoyuan
 */
public class CodeService {

    /** freemaker 配置 */
    private Configuration cfg;

    /** 操作池 */
    DBMangerPool dBMangerPool = DBMangerPool.getInstance();

    /** 项目路径 */
    private String projectPath;

    /**
     * 自动生成代码
     * @param treePath 树
     * @param myPackage 包名
     * @param model 模块
     * @param subModel 子模块
     * @param authorNm 作者
     * @return
     */
    public String auotoCode(String templatePath,TreePath[] treePath,String myPackage,String model,String subModel,String projectPath,String authorNm){
        String msg = "";
        //设置项目路径
        this.projectPath = projectPath;
        try {
            // 获得freemaker 配置
            cfg = ConfigurationHelper.getConfiguration(templatePath);
            // 获取操作类的key、数据库目录、表名
            String key, catalog, table, tableDesc = "", className = "";
            List<ColumnModel> columns = null;
            for (int i = 0; i < treePath.length; i++) {
                TreePath tmp = treePath[i];
                if (tmp.getPath().length < 3) {
                    continue;
                }
                key = Config.dbKey;
                catalog = tmp.getPath()[1].toString();
                table = tmp.getPath()[2].toString();
                tableDesc = table.substring(table.indexOf("(") + 1,
                        table.lastIndexOf(")"));
                table = table.substring(0, table.indexOf("("));
                columns = dBMangerPool.getDBManger(key).getColumnsByTable(
                        catalog, table);
                className = StringUtils.toClassName(table);
                String resultMsg = this.doCreate(templatePath,className,myPackage,model,subModel, tableDesc, columns, table, authorNm);
                msg += resultMsg;
            }
            if(msg == null || "".equals(msg)){
                msg = "生成成功";
            }else{
                msg = "生成成功\n\t" + msg;
            }
        } catch (Exception e) {
            e.printStackTrace();
            msg = e.getMessage();
        }
        return msg;
    }

    /**
     * 多文件生成
     * @param className 类名
     * @param myPackage 包名
     * @param model 模块
     * @param subModel 子模块
     * @param tableDesc 表描述
     * @param columns 列
     * @param table 表
     * @throws Exception
     */
    public String doCreate(String templatePath,String className,String myPackage,String model,String subModel, String tableDesc,
                        List<ColumnModel> columns, String table ,String authorNm) throws Exception {
        // 装载model数据
        TableModel tableModel = new TableModel();
        tableModel.setPackageName(myPackage);
        tableModel.setModel(model);
        tableModel.setSubModel(subModel);
        tableModel.setClassName(className);
        tableModel.setColumns(columns);
        tableModel.setTableDesc(tableDesc);
        tableModel.setTableName(table);
        tableModel.setAuthorNm(authorNm);
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tableModel.setCreateTime(df.format(new Date()));

        //代码存放路径
        String codePath = "src.main.java.";
        //sql文件存放路径
        String sqlPath = "src.main.resources.mappings.";
        //jsp文件存放路径
        String jspPath = "src.main.webapp.WEB-INF.view.";

        /** 开始生成实体类 */
        String pojoPath = codePath+myPackage+"."+model;
        if (subModel!=null){
            pojoPath = pojoPath+"."+subModel;
        }
        pojoPath = pojoPath+".entity";
        if(Config.templatePath.equals(templatePath)) {
            save(tableModel, "Pojo.java.ftl", pojoPath,
                    className + ".java");
        }else if(Config.templateSpringBootPath.equals(templatePath)){
            save(tableModel, "Pojo.java.ftl", pojoPath,
                    className + "Entity.java");
        }else if(Config.TEMPLATE_VUE_MANAGEPATH.equals(templatePath)){
            String resultMsg = "";
            /** 输出 route路由 */
            resultMsg += "/--------------------- route路由开始 ---------------------/\n\t";
            resultMsg += save(tableModel, "list.vue.ftl", "","list.vue") + "\n\t";
            resultMsg += save(tableModel, "edit.vue.ftl", "","edit.vue") + "\n\t";
            resultMsg += "/--------------------- route路由结束 ---------------------/\n\t";

            return resultMsg;
        }

        /** 开始生成Dao接口 */
        String daoPath = codePath+myPackage+"."+model;
        if (subModel!=null){
            daoPath = daoPath+"."+subModel;
        }
        daoPath = daoPath+".dao";
        save(tableModel, "Dao.java.ftl", daoPath,
                className + "Dao.java");

        /** 开始生成Dao.xml文件 */
        String mapperPath = sqlPath+model;
        save(tableModel, "Mapper.xml.ftl", mapperPath, className + "Dao.xml");

        /** 开始生成Service */
        String servicePath = codePath+myPackage+"."+model;
        if (subModel!=null){
            servicePath = servicePath+"."+subModel;
        }
        servicePath = servicePath+".service";
        save(tableModel, "Service.java.ftl", servicePath,
                className + "Service.java");

        /** 开始生成Controller */
        String controllerPath = codePath+myPackage+"."+model;
        if (subModel!=null){
            controllerPath = controllerPath+"."+subModel;
        }
        controllerPath = controllerPath+".controller";
        save(tableModel, "Controller.java.ftl", controllerPath, className + "Controller.java");

        if(Config.templatePath.equals(templatePath)){
            // 开始生成页面
            String viewPath = jspPath+model+"."+StringUtils.toLowerCaseFirstOne(className);
            save(tableModel, "Add.jsp.ftl", viewPath,"add.jsp");
            save(tableModel, "Edit.jsp.ftl", viewPath,"edit.jsp");
            save(tableModel, "List.jsp.ftl", viewPath,"list.jsp");
            save(tableModel, "View.jsp.ftl", viewPath,"view.jsp");
        }
        return "";
    }

    /**
     * 保存到文件
     *
     * @return
     * @throws Exception
     */
    public String save(TableModel tableModel, String templateName, String path, String fileName) throws Exception {
        String resultMsg = "";
        try {
            // 装载model数据
            Map<String, Object> data = new HashMap<String, Object>();
            data.put("model", tableModel);
            // 获得模板对象
            Template template = cfg.getTemplate(templateName);
            //设置编码
            template.setEncoding("UTF-8");
            // 创建生成类的存放路径
            path = path.replaceAll("\\.", "/");
            FileUtils.forceMkdir(new File(projectPath + File.separator + path));
            File output = new File(projectPath + File.separator + path, fileName);
//        File output = new File(projectPath , fileName);
            FileOutputStream fos = new FileOutputStream(output);
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(osw, 1024);
            // 开始创建
            template.process(data, bw);
            // 构造路由数据
            resultMsg = "{\n\t";
            resultMsg += "    path: '"+ tableModel.getModel() +"/"+ tableModel.getClassName() +"/list',\n\t";
            resultMsg += "    name: '"+ tableModel.getModel() +"/"+ tableModel.getClassName() +"/list',\n\t";
            resultMsg += "    component: () => import('@/pages/"+ tableModel.getModel() +"/"+ tableModel.getTableName() +"/list'),\n\t";
            resultMsg += "    meta: { ...meta, title: '"+ tableModel.getTableDesc() +"管理' }\n\t";
            resultMsg += "}";
            fos.close();
            osw.close();
            bw.close();
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("有异常，但什么也不做");
            resultMsg = "其实是出错了";
        }
        return resultMsg;
    }





    public String auotoCodeTest(TreePath[] treePath,String myPackage,String model,String subModel,String projectPath,String authorNm){
        String msg = null;
        //设置项目路径
        this.projectPath = projectPath;
        try {
            // 获得freemaker 配置
            cfg = ConfigurationHelper.getConfiguration(Config.templatePath);
            // 获取操作类的key、数据库目录、表名
            String key, catalog, table, tableDesc = "", className = "";
            List<ColumnModel> columns = null;
            for (int i = 0; i < treePath.length; i++) {
                TreePath tmp = treePath[i];
                if (tmp.getPath().length < 3) {
                    continue;
                }
                key = Config.dbKey;
                catalog = tmp.getPath()[1].toString();
                table = tmp.getPath()[2].toString();
                tableDesc = table.substring(table.indexOf("(") + 1,
                        table.lastIndexOf(")"));
                table = table.substring(0, table.indexOf("("));
                columns = dBMangerPool.getDBManger(key).getColumnsByTable(
                        catalog, table);
                className = StringUtils.toClassName(table);
                shuntTest(className,myPackage,model,subModel, tableDesc, columns, table, authorNm);
            }
            msg = "生成成功";
        } catch (Exception e) {
            e.printStackTrace();
            msg = e.getMessage();
        }
        return msg;
    }


    /**
     * 生成数据库结构文件
     * @author GaoYuan
     * @datetime 2018/3/9 上午10:52
     */
    public String autoCreateDoc(TreePath[] treePath,String projectPath){
        String msg = null;
        //设置项目路径
        this.projectPath = projectPath;
        try {
            // 获得freemaker 配置
            cfg = ConfigurationHelper.getConfiguration(Config.templatePath);
            // 获取操作类的key、数据库目录、表名
            String key, catalog, table, tableDesc = "", className = "";
            List<ColumnModel> columns = null;
            DataBaseModel dataBaseModel = new DataBaseModel();
            List<TableModel> tableModelList = new ArrayList<>();
            TableModel tableModel = null;
            for (int i = 0; i < treePath.length; i++) {
                TreePath tmp = treePath[i];
                if (tmp.getPath().length < 3) {
                    continue;
                }
                key = Config.dbKey;
                catalog = tmp.getPath()[1].toString();
                dataBaseModel.setDbName(catalog);

                table = tmp.getPath()[2].toString();
                tableDesc = table.substring(table.indexOf("(") + 1, table.lastIndexOf(")"));
                table = table.substring(0, table.indexOf("("));
                columns = dBMangerPool.getDBManger(key).getColumnsByTable(catalog, table);

                tableModel = new TableModel();

                tableModel.setTableName(table);
                tableModel.setTableDesc(tableDesc);
                tableModel.setColumns(columns);
                tableModelList.add(tableModel);
            }

            dataBaseModel.setTableModelList(tableModelList);

            save(dataBaseModel,"Html.ftl","",dataBaseModel.getDbName()+".html");

            msg = "生成成功";
        } catch (Exception e) {
            e.printStackTrace();
            msg = e.getMessage();
        }
        return msg;
    }



    public void shuntTest(String className,String myPackage,String model,String subModel, String tableDesc,
                      List<ColumnModel> columns, String table ,String authorNm) throws Exception {
        // 装载model数据
        TableModel tableModel = new TableModel();
        tableModel.setPackageName(myPackage);
        tableModel.setModel(model);
        tableModel.setSubModel(subModel);
        tableModel.setClassName(className);
        tableModel.setColumns(columns);
        tableModel.setTableDesc(tableDesc);
        tableModel.setTableName(table);
        tableModel.setAuthorNm(authorNm);
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tableModel.setCreateTime(df.format(new Date()));

        //代码存放路径
        String codePath = "src.main.java.";
        //sql文件存放路径
        String sqlPath = "src.main.resources.mappings.";
        //jsp文件存放路径
        String jspPath = "src.main.webapp.WEB-INF.view.";


        // 开始生成Controller
        String controllerPath = codePath+myPackage+"."+model;
        if (subModel!=null){
            controllerPath = controllerPath+"."+subModel;
        }
        controllerPath = controllerPath+".controller";
        save(tableModel, "Test.java.ftl", controllerPath, className + "Test.java");

    }


    /**
     * 保存到文件
     * @return
     * @throws Exception
     */
    public void save(DataBaseModel dataBaseModel, String templateName, String path, String fileName) throws Exception {
        System.out.println("--开始导入--");
        // 装载model数据
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("dataBaseModel", dataBaseModel);
        // 获得模板对象
        Template template = cfg.getTemplate(templateName);
        //设置编码
        template.setEncoding("UTF-8");
        // 创建生成类的存放路径
        path = path.replaceAll("\\.","/");
        FileUtils.forceMkdir(new File(projectPath + File.separator + path));
        File output = new File(projectPath + File.separator +path, fileName);
//        File output = new File(projectPath , fileName);
        FileOutputStream fos= new FileOutputStream(output);
        OutputStreamWriter osw =new OutputStreamWriter(fos, "UTF-8");
        BufferedWriter bw =new BufferedWriter(osw, 1024);
        // 开始创建
        template.process(data, bw);
        fos.close();
        osw.close();
        bw.close();
    }



}
